using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.Intrinsics.Arm;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using AppDown.Db;
using AppDown.Db.Models;
using AppDown.Db.Models.Base;

namespace AppDown.Controllers.Base
{
    /// <summary>
    /// 基类Api
    /// </summary>
    public class BaseApi : ControllerBase
    {
        /// <summary>
        /// sqlsugar单例对象
        /// </summary>
        public SqlSugarScope db = SqlSugarHelper.Db;


        #region 保存

        /// <summary>
        /// 保存单条数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<bool> SaveAsync<T>(T model) where T : BaseEntity, new()
        {
            var x = db.Storageable(model).ToStorage();
            int insterResult = await x.AsInsertable.ExecuteCommandAsync();
            int updateResult = await x.AsUpdateable.ExecuteCommandWithOptLockAsync();
            //TODO 有空再弄严谨一点
            return true;
        }

        /// <summary>
        /// 保存多条数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<bool> SaveAsync<T>(List<T> model) where T : BaseEntity, new()
        {
            var x = db.Storageable(model).ToStorage();
            int insterResult = await x.AsInsertable.ExecuteCommandAsync();
            int updateResult = await x.AsUpdateable.ExecuteCommandWithOptLockAsync();
            //TODO 有空再弄严谨一点
            return true;
        }

        #endregion

        #region 删除

        /// <summary>
        /// 删除一条指定主键ID的数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<bool> DeleteAsync<T>(int id) where T : BaseEntity, new() => await db.Deleteable<T>().Where(a => a.Id == id).ExecuteCommandAsync() > 0;

        #endregion

        #region 普通查询

        /// <summary>
        /// 获取单个数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="expression"></param>
        /// <returns></returns>
        public async Task<T> GetAsync<T>(Expression<Func<T, bool>> expression) => await db.Queryable<T>().Where(expression).FirstAsync();

        /// <summary>
        /// 获取数据列表
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="expression"></param>
        /// <returns></returns>
        public async Task<List<T>> GetListAsync<T>(Expression<Func<T, bool>> expression) => await db.Queryable<T>().Where(expression).ToListAsync();


        #endregion

        #region 分页查询


        [NonAction]
        public async Task<object> GetPage<T>(ReqPage model, bool isWhere, Expression<Func<T, bool>> expression, Expression<Func<T, object>>? orderByexpression = null, OrderByType type = OrderByType.Asc)
        {
            //单表分页
            RefAsync<int> total = 0;//REF和OUT不支持异步,想要真的异步这是最优解
            var lstQuery = db.Queryable<T>();

            var lst = await lstQuery.WhereIF(isWhere, expression)
                .OrderByIF(orderByexpression != null, orderByexpression, type)
                 .ToPageListAsync(model.PageNumber, model.PageSize, total);

            return new ResPage
            {
                Data = lst,
                PageSize = model.PageSize,
                PageNumber = model.PageNumber,
                Total = total
            };

        }

        [NonAction]
        public async Task<object> GetPage<T>(ReqPage model, Dictionary<bool, Expression<Func<T, bool>>> whereIFs)
        {
            //单表分页
            RefAsync<int> total = 0;//REF和OUT不支持异步,想要真的异步这是最优解
            var lstQuery = db.Queryable<T>();

            foreach (var whereIF in whereIFs)
            {
                lstQuery = lstQuery.WhereIF(whereIF.Key, whereIF.Value);
            }

            var lst = await lstQuery
                 .ToPageListAsync(model.PageNumber, model.PageSize, total);

            return new ResPage
            {
                Data = lst,
                PageSize = model.PageSize,
                PageNumber = model.PageNumber,
                Total = total
            };

        }

        #endregion


        [NonAction]
        public ApiResult Success(object data, string msg = "成功")
        {
            return new ApiResult() { Code = 200, Data = data, Msg = msg };
        }

        [NonAction]
        public ApiResult SuccessMsg(string msg = "执行成功")
        {
            return new ApiResult() { Code = 200, Data = new { }, Msg = msg };
        }

        [NonAction]
        public ApiResult Error(string msg)
        {
            return new ApiResult() { Code = 401, Data = new { }, Msg = msg };
        }


        [NonAction]
        public bool CheckIsInitSystem()
        {
            if (
                db.DbMaintenance.IsAnyTable(nameof(AppDownLoad), false)
                )
            {
                return true;
            }

            return false;
        }

    }

    public class DataPageBase
    {
        public int PageSize { get; set; } = 10;
        public int PageNumber { get; set; } = 1;
        public int Total { get; set; }

    }

    public class ReqPage : DataPageBase
    {
        public string Key { get; set; }
    }

    public class ResPage : DataPageBase
    {
        public object Data { get; set; }
    }

    public class ApiResult
    {
        public int Code { get; set; }
        public string Msg { get; set; }
        public object Data { get; set; }
    }
}